package com.dfhc.pub.concurrencycontrol;

import java.util.ArrayList;
import java.util.List;

import com.dfhc.util.ConvertHelper;
import com.dfhc.util.StringHelper;

/**
 * @author longsebo
 * 根据guid路由到对应的RequestConcurrentLock
 */
public class RequestConcurrentRoute {
	private static RequestConcurrentRoute requestConcurrentRoute;
	/**
	 * 锁队列
	 */
	private List<RequestConcurrentLock> lockList = new ArrayList<RequestConcurrentLock>();
	/**
	 * 获取单例
	 * @return
	 */
	public static synchronized RequestConcurrentRoute getSingleton(){
		if(requestConcurrentRoute==null){
			requestConcurrentRoute = new RequestConcurrentRoute();
		}
		return requestConcurrentRoute;
	}
	public void initSize(int num){
		if(num<1){
			//throw new PjException("无效锁队列大小!"+num);
			//默认为10
			num=10;
		}
		for(int i=0;i<num;i++){
			lockList.add(new RequestConcurrentLock());
		}
	}
	/**
	 * 根据guid加锁,如果guidList存在这个guid，则报错
	 * @param guid
	 * @return
	 */
	public boolean lock(String guid){
		//如果guid为空，则返回false
		if(StringHelper.isEmpty(guid)){
			return false;
		}
		int index = calcuRoute(guid);
		
		return lockList.get(index).lock(guid);
	}
	/**
	 * 计算路由下标
	 * @param guid
	 * @return
	 */
	private int calcuRoute(String guid) {
		//根据lockList长度，决定取几个字符串参与运算
		String strSize = ConvertHelper.toString(lockList.size());
		int sum =0;
		for(int i=guid.length()-1;i>=0 && i>=guid.length()-strSize.length();i--){
			sum = sum +guid.charAt(i);
		}
		int index = sum % lockList.size();
		if(index<0 ||index>lockList.size()){
			return 0;
		}else{
			return index;
		}
	}
	/**
	 * 根据guid解锁，从guidList删除guid
	 * @param guid
	 */
	public void unLock(String guid,boolean bLock){
		if(bLock){
		int index = calcuRoute(guid);
		lockList.get(index).unLock(guid);
		}
	}
	/**
	 * 根据guid加锁,如果guidList存在这个guid，则等待指定时间，如果超时后guidList还存在这个guid，则报错
	 * @param guid
	 * @param waitTime 毫秒为单位
	 * 
	 * @return
	 */
	public boolean lock(String guid,long waitTime){
		//如果guid为空，则返回false
		if(StringHelper.isEmpty(guid)){
			return false;
		}
		int index = calcuRoute(guid);
		
		return lockList.get(index).lock(guid,waitTime);
	}
}
